#include <inc/types.h>
#include <inc/acpi.h>
#include <inc/string.h>
#include <inc/stdio.h>

struct numa_node node[8];


static struct rsdp *rsdp_search(uint64_t base, uint32_t limit)
{
	uint32_t offset = 0;
	uint8_t *rsdp;

	while(offset < limit)
	{
		rsdp = (uint8_t *)(base + offset);
		/*if(rsdp->sig[0] == 'R' && rsdp->sig[1] == 'S' && rsdp->sig[2] == 'D' &&
		rsdp->sig[3] == ' ' && rsdp->sig[4] == 'P' && rsdp->sig[5] == 'T' &&
		rsdp->sig[6] == 'P' && rsdp->sig[7] == ' ')*/
		if(memcmp(rsdp, "RSD PTR ", 8) == 0)
			return (struct rsdp *)rsdp;
		offset += 16;
	}
	return 0;
}

struct rsdp *rsdp_get(void)
{
	uint8_t *data;
	uint16_t addr;
	struct rsdp *rsdp;
	data = (uint8_t *)400;
	addr = (data[0xe] | (data[0xf]<<8))<<4;
	if((rsdp = rsdp_search(addr, 1024)) != 0)
		return rsdp;
	if((rsdp = rsdp_search(0xe0000,0x1ffff)) != 0)
		return rsdp;
	return 0;
}

struct srat *srat_get(struct xsdt *xt)
{
	struct srat *aff;
	uint32_t index = 0;

	index = (xt->header.length - sizeof(struct des_header))/8;

	for(uint32_t i = 0; i < index; i ++)
	{
		aff = (struct srat *) xt->entry[i];
		if(memcmp(aff->header.sig, "SRAT", 4) == 0)
			return aff;
	}
	return 0;
}

struct ivrs *ivrs_get(struct xsdt *xt)
{
	struct ivrs *ivrs;
	uint32_t index = 0;

	index = (xt->header.length - sizeof(struct des_header))/8;

	for(uint32_t i = 0; i < index; i ++)
	{
		ivrs = (struct ivrs *) xt->entry[i];
		if(memcmp(ivrs->header.sig, "IVRS", 4) == 0)
			return ivrs;
	}
	return 0;
}

int srat_parse(struct srat *srat)
{
	char *p = 0;
	struct apic_aff *apic_aff = 0;
	struct mem_aff *mem_aff = 0;
	uint32_t domain_id;
	uint32_t entr_len;
	uint32_t i = 0, j = 0;
	entr_len = srat->header.length - sizeof(struct des_header) - 8;
	p = (char *)srat->entry;
	

	for(; p < (char *)srat->entry +  entr_len;)
	{
 		if(p[0] == 0 && p[1] == 16)
		{
			apic_aff = (struct apic_aff *)p;
			domain_id = (uint32_t) apic_aff->proxi_domain
				+ (((uint32_t) apic_aff->proxi_domain1[0])<<8)
				+ (((uint32_t) apic_aff->proxi_domain1[1])<<16)
				+ (((uint32_t) apic_aff->proxi_domain1[2])<<24);
			node[domain_id].id = domain_id;
			node[domain_id].lapicid[node[domain_id].index] = apic_aff->apic_id;
			node[domain_id].index ++;
			p = p + 16;
			i ++;
		}
		else if(p[0] == 1 && p[1] == 40)
		{
			mem_aff = (struct mem_aff *)p;
			domain_id = (uint32_t) mem_aff->proxi_domain;
			node[domain_id].id = domain_id;
			node[domain_id].base_addr = (uint64_t) mem_aff->base_addr_low
				+ (((uint64_t) mem_aff->base_addr_high)<<32);
			node[domain_id].length = (uint64_t ) mem_aff->length_low
				+ (((uint64_t) mem_aff->length_high)<<32);
			p = p + 40;
			j ++;
		}
		else
		{
			cprintf("total apic_aff is %u  and mem_aff is %u bad srat\n", i, j);
			return -1;
		}
	}
	return 0;
}

